package edu.washington.ling.syntric.util;

import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;

import edu.washington.ling.syntric.io.Example;
import edu.washington.ling.syntric.struct.rule.BiDSPattern;
import edu.washington.ling.syntric.struct.rule.BiPSPattern;
import edu.washington.ling.syntric.struct.rule.UniDSPattern;
import edu.washington.ling.syntric.struct.rule.UniPSPattern;
import edu.washington.ling.syntric.struct.tree.Node;
import edu.washington.ling.syntric.struct.tree.Token;


public class ConvertUtils {
	
	public static Map<String, String> getStackingRules() {
		Map<String, String> stackingRules = new HashMap<String, String>();
		stackingRules.put("VM_VP","rightTop");
		return stackingRules;
	}
	
	public static boolean isCompatible(Example exr) {
		return isCompatible(exr, false);
	}
	
	public static boolean isCompatible(Example exr, boolean onlyMapPOS) {
		boolean isCompatible = false;
		if (exr.hasTreeRep("DS-Const") && exr.hasTreeRep("PS")) {
			if (onlyMapPOS) {
				isCompatible = true;
			}
			else if (!exr.getTreeRep("DS-Const").hasMetaData("inconsistent")) {
				isCompatible = true;
			}
		}
		return isCompatible;
	}
	
	public static Token getPatternToken(Token t, String[] extrFeats, boolean useExtPOS) {
		Token pattToken = new Token();
		pattToken.setTag(t.getTag());
		if (useExtPOS && t.hasFeature("Ext-POS")) {
			pattToken.setTag(t.getValue("Ext-POS"));
		}
		for (String feat: extrFeats) {
			if (t.hasFeature(feat)) {
				pattToken.setFeature(feat, t.getValue(feat));
			}
		}
		return pattToken;
	}
	
	public static Node getPatternNode(Node n) {
		Node pattNode = new Node();
		pattNode.setLabel(n.getLabel().replaceFirst("([\\=\\-]\\d+)+$", ""));
		return pattNode;
	}
	
	public static BiDSPattern extractBinaryDSPattern(Token dsDependent, Token dsHead, 
			String[] extrDepFeats, String[] extrHeadFeats, boolean useExtPOS) {
		Token dsPattChild = getPatternToken(dsDependent, extrDepFeats, useExtPOS);
		Token dsPattParent = getPatternToken(dsHead, extrHeadFeats, useExtPOS);
		return new BiDSPattern(dsPattChild, dsPattParent);
	}
	
	public static BiPSPattern extractBinaryPSPattern(Token dsDependent, Token dsHead) {
		List<Node> psParentChain = new LinkedList<Node>();
		Node psParent = TreeUtils.markLCA(dsDependent, dsHead);
		if (psParent.hasPSParent()) {
			Node psGrandparent = psParent.getPSParent();
			if (psGrandparent.getPSChildren().size() == 1) {
				psParentChain.add(getPatternNode(psGrandparent));
			}
		}
		psParentChain.add(getPatternNode(psParent));
		Node psChild = getPatternNode(TreeUtils.getChildOfLCA(dsDependent));
		Node psHeadChild = getPatternNode(TreeUtils.getChildOfLCA(dsHead));
		TreeUtils.unMarkLCA(dsDependent);
		return new BiPSPattern(psParentChain, psChild, psHeadChild);
	}

	
	public static UniDSPattern extractUnaryDSPattern(Token dsToken, String[] extrFeats,
			boolean useExtPOS) {
		Token pattToken = getPatternToken(dsToken, extrFeats, useExtPOS);
		return new UniDSPattern(pattToken);
	}
	
	public static UniPSPattern extractUnaryPSPattern(Token dsToken) {
		return extractUnaryPSPattern(dsToken, Integer.MAX_VALUE);
	}
	public static UniPSPattern extractUnaryPSPattern(Token dsToken, int maxLength) {
		ArrayList<Node> psNodes = new ArrayList<Node>();
		Node n = dsToken;
		while(n.hasPSParent() && (psNodes.size() < maxLength)) {
			n = n.getPSParent();
			if(n.getPSChildren().size() == 1) {
				psNodes.add(0, getPatternNode(n));
			} else {
				break;
			}
		}
		return new UniPSPattern(psNodes);
	}
	
}
